#include<bits/stdc++.h> 
using namespace std;
//	与甲级1048同背景。这题在原来的基础上需要花出的硬币应该满足如果有两种花法，那么我们
//	将这两种花法的钱从小到大排序后，逐个比对，找到第一个不同的元素，其中小的那种就是我
//	们要的 
//1.DFS，性能题
//网上说这题不能用DFS，肯定超时，但是我就DFS写了，然后耗时全部≤4ms，内存也都在450以下
//所以还是可以做的。其实这道题只需要early stop就不会超时。由于题目中说的要找的花法很特
//殊，DFS确实可以找到很多花法，但是符合条件的绝对是第一条。因为我们首先对硬币面值进行了
//排序，所以我们从前往后DFS的时候，第一条找到的路肯定就是我们所需要的那条。 
//所以优化点1：找到一条路就直接停止DFS，然后也不用做其他操作，直接返回即可
//优化点2：在DFS的过程中，一旦累和大于M，就直接停止该结点的DFS，然后返回上一层
//优化点3：做这些操作前先看看所有的硬币加起来有没有可能达到M，如果达不到，那么循环的次数
//将达到最大，这个是很浪费时间的。达不到的话直接输出不行就OK了 
vector<int> bestPath;	//存放最优解 
vector<int> path;	//存放中间过程 
int V[10000];	//存放硬币面值 
int sum_;	//存放DFS过程中目前中间过程的面值和 
int N,M;	
void DFS(int now){	//传入下标，向量中存的也是下标 
	sum_ += V[now];	//之前的总和加上当前遍历的这个硬币 
	path.push_back(now);	//把它压入向量 
	if(sum_ == M){	//如果和达到了M，就直接把中间结果给最优向量 
		bestPath = path;
		return; 
	}
	else{	//如果低于，则继续递归 
		for(int i = now+1;i<N;i++){	//从当前结点的后一个开始递归 
			if(bestPath.size()!=0) return;	//一旦检测到已经得到最优解的信号就直接返回 
			if(sum_+V[i]<=M) DFS(i);	//否则，如果已知和小于等于再DFS，不然直接停止后续的DFS即可 
			else break;
		}
		path.pop_back();
		sum_ -= V[now];
	}
}
int main(){
	cin>>N>>M;
	int t=0;
	for(int i = 0;i<N;i++){ 
		cin>>V[i];
		t+=V[i];
	}
	if(t<M){
		cout<<"No Solution"<<endl;
		return 0;
	}
	sort(V,V+N);
	for(int i = 0;i<N;i++){	//如果只是DFS(0)的话，测试点2会过不去的，因为可能并不是从第0个开始作为解 
		if(bestPath.size()==0) DFS(i);
	}
	
	if(bestPath.empty()) cout<<"No Solution"<<endl;
	else{
		for(unsigned int i = 0;i<bestPath.size();i++){
			cout<<V[bestPath[i]];
			if(i==bestPath.size()-1) cout<<endl;
			else cout<<" ";
		}
	}
	return 0;
} 